package com.franklin.ideaplugin.maphelper.completion.result.impl;

import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.completion.result.IMapLookupElementBuilder;
import com.franklin.ideaplugin.maphelper.icons.PluginIcons;
import com.google.common.collect.Lists;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiExpression;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * @author Ye Junhui
 * @since 2024/3/7
 */
public class DefaultMapLookupElementBuilder implements IMapLookupElementBuilder {

    public final static DefaultMapLookupElementBuilder INSTANCE = new DefaultMapLookupElementBuilder();

    @Override
    public boolean support(PsiExpression psiExpression) {
        PsiClassType psiClassType = (PsiClassType) psiExpression.getType();
        return true;
    }

    @Override
    public @NotNull List<LookupElementBuilder> buildLookupElement(PsiExpression psiExpression, IColMember colMember) {
        LookupElementBuilder getMethod = buildGetMethod(psiExpression, colMember);
        LookupElementBuilder getOrDefaultMethod = buildGetOrDefaultMethod(psiExpression, colMember);

        return Lists.newArrayList(getMethod,getOrDefaultMethod);
    }

    /**
     * 构建get方法
     * @param psiExpression
     * @param colMember
     * @return
     */
    private LookupElementBuilder buildGetMethod(PsiExpression psiExpression, IColMember colMember){
        String keyText = colMember.getKeyText();
        String typeText = colMember.getValueClassSimple();

        //get方法
        LookupElementBuilder getMethod = LookupElementBuilder.create(String.format("get(%s)", keyText))
                .withIcon(PluginIcons.PLUGIN_ICON)
                .withTypeText(typeText)
                .withInsertHandler(new InsertHandler<LookupElement>() {

                    private final static String FILL_EXPRESSION_TEMPLATE = "(%s)%s.get(%s)";

                    @Override
                    public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
                        int startOffset = psiExpression.getFirstChild().getTextOffset();
                        String input = String.format(FILL_EXPRESSION_TEMPLATE, typeText, psiExpression.getText(), keyText);
                        Document document = context.getDocument();
                        document.replaceString(startOffset, context.getTailOffset(), input);
                        context.commitDocument();
                    }
                });

        return getMethod;
    }

    /**
     * 构建getOrDefault方法
     * @param psiExpression
     * @param colMember
     * @return
     */
    private LookupElementBuilder buildGetOrDefaultMethod(PsiExpression psiExpression, IColMember colMember){
        String keyText = colMember.getKeyText();
        String typeText = colMember.getValueClassSimple();

        //get方法
        LookupElementBuilder getMethod = LookupElementBuilder.create(String.format("getOrDefault(%s)", keyText))
                .withIcon(PluginIcons.PLUGIN_ICON)
                .withTypeText(typeText)
                .withInsertHandler(new InsertHandler<LookupElement>() {

                    private final static String FILL_EXPRESSION_TEMPLATE = "(%s)%s.getOrDefault(%s,)";

                    @Override
                    public void handleInsert(@NotNull InsertionContext context, @NotNull LookupElement item) {
                        int startOffset = psiExpression.getFirstChild().getTextOffset();
                        String input = String.format(FILL_EXPRESSION_TEMPLATE, typeText, psiExpression.getText(), keyText);
                        Document document = context.getDocument();
                        document.replaceString(startOffset, context.getTailOffset(), input);
                        context.commitDocument();
                        int moveOffset = startOffset + input.length() - 1;
                        context.getEditor().getCaretModel().moveToOffset(moveOffset);
                    }
                });

        return getMethod;
    }
}
